perm filename MAPS1.SAI[SYS,HE]4 blob sn#052046 filedate 1973-07-03 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00016 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	MAPS1 - programs for the parsing of the scene.
C00006 00003	_ external and forward procedures - LCRV
C00008 00004	_ DTRCE, LINDL, QTRCE
C00010 00005	_ MLCR, REVIVE, UPPDAL
C00012 00006	_ UNTST, BREAK
C00014 00007	_ CLUPSC
C00017 00008	_ FUSABL
C00021 00009	_ LFDIF
C00026 00010	_ MAP (VCRKEY)
C00030 00011	_ PARSE
C00033 00012	_ PARSE cont
C00035 00013	_ PARSE cont
C00038 00014	_ PARSE cont
C00040 00015	_ PARSE cont
C00042 00016	_ PARSE cont
C00045 ENDMK
C⊗;
COMMENT MAPS1 - programs for the parsing of the scene.;

ENTRY LCRV,LCRL,DTRCE,LINDL,QTRCE,MLCR,REVIVE,CLUPSC,
      UPPDAL,FUSABL,LFDIF,MAP,PARSE;

BEGIN "MAPS1"

DEFINE QC(I)="&""  I=""&CVS(I)",
	QCO(I)="&""  I=""&CVOS(I)",
	QCR(R)="&""  R=""&CVF(R)",
	NOTHING="",
	CL="'15&'12",
	QSCOR="&""   SCORE=""&CVOS(CMPL+1)&""/""&CVOS(SCO)",
	BL="'40",
	QENP="EXTERNAL PROCEDURE",
	QS="STRING",
	QESP="EXTERNAL SIMPLE STRING PROCEDURE",
	QI="INTEGER",
	QR="REAL",
	QRI="REFERENCE INTEGER",
	QRR="REFERENCE REAL",
	QEP="EXTERNAL SIMPLE PROCEDURE",
	QEIP="EXTERNAL SIMPLE INTEGER PROCEDURE",
	QERP="EXTERNAL SIMPLE REAL PROCEDURE",
	QFOP="FORWARD INTERNAL SIMPLE PROCEDURE",
	QFOIP="FORWARD INTERNAL SIMPLE INTEGER PROCEDURE",
	QFORP="FORWARD INTERNAL SIMPLE REAL PROCEDURE",
	_="COMMENT",
	LOOP(I,J,K,L)="FOR I←J STEP L UNTIL K DO",
	QTRC="IF DTRACE∨MAPTRC LAND '12000 THEN QTRCE",
	DTRC="IF DTRACE∨MAPTRC LAND '10000 THEN DTRCE",
	LINSET="DISW←1; DTRC(""LINSRT:""QC(IFREEL)); LINSRT",
	BELCRE(I)="LVNEXT(I,-1)",
	SAFEX="SAFE";
INTEGER IA,DCHAN,CURMAP;
INTERNAL INTEGER PROT,PLIN,PVER,AD0,LNCS1,LNCS2,RAYS,ICH,CMPIND,
	BRCH,EOF,DTRACE,KMP,RUL,MDCTR,DISW,FLMIND,FTSW,LFDBT,BESTMP,NPRS,
	N1,N2,TC,TCS,LNCRE0;
EXTERNAL INTEGER NOEPA,NOL,MAXNOL,MAXNOV,LNCRE1,LNCRE2,
	PFTOT,MODIF,PLFTOT,MAXPLS,MAXPVS,MAPTRC,SCO,CMPL;
EXTERNAL REAL RWIC,RMAP;
SAFEX EXTERNAL INTEGER ARRAY DICH[0:1],LCREDE,LFEAT,LVERCO,LINK,
	LVERSI,PLINES,PVERTS,PPTRL,PLINE,PLINE2,PFPRO,PFEAT,
	LVER,CFEAT[1:1],PFPTR[0:1];
SAFEX EXTERNAL REAL ARRAY XVCOR,YVCOR,XLCOR,YLCOR,CXL,CYL,CCL,RLEN[1:1];
SAFEX EXTERNAL STRING ARRAY PNAME[1:1];
_ external and forward procedures - LCRV;

QEP LINDEL(QI I,J);
QEIP BITS(QI I,J,K);
QEIP MAPCONV(QS CODES);
QEIP INREK(QR X,Y);
QEP UPPDAT;
QEP FTEX;
QENP XREFC(QI I);
QEP UNXREF;
QEIP LACT(QI I);
QERP ANGLIN(QI I,J);
QEIP LVOPP(QI I);
QERP SQRT(QR R);
QEIP MAX0(QI I,J);
QEIP KARN(QR X1,Y1,X2,Y2,X3,Y3,X4,Y4; QI IC);
QEP REKOP(QR X1,Y1,X2,Y2,WI; QRR RL);
QEP WEIGHV(QI I; QRR X,Y,WE);
QEIP MAPREC;
QEP PRECAL;
QEP CALC;
QEIP LVNEXT(QI I,J);
QEP REGREF(INTEGER I);
QEIP MSCVCO(QI ISV, ICV, LADD);
QEIP NEXVER;
QEIP LCRL(QI L);

_ return LCREDE entry for s.v. SV (sign and low 4 octal digits only);

INTERNAL SIMPLE INTEGER PROCEDURE LCRV(INTEGER SV);
	RETURN(LCREDE[(SV+1)%2] LAND '400000007777);

_ DTRCE, LINDL, QTRCE;

_ Produces trace output on file "PARSE.TRC" if MAPREC bit 12 is set.;

INTERNAL SIMPLE PROCEDURE DTRCE(STRING S);
	BEGIN "DTRC"
	IF DTRACE∧DCHAN=-1∨¬DTRACE∧(DTRACE←MAPTRC LAND '10000) THEN
		BEGIN
		OPEN(DCHAN←GETCHAN,"DSK",0,0,2,100,BRCH,EOF);
		ENTER(DCHAN,"PARS"&CVS(NPRS←NPRS+1)&".TRC",IA)
		END;
	IF DTRACE∧¬(DTRACE←MAPTRC LAND '10000) THEN
		 BEGIN CLOSE(DCHAN); DCHAN←-1 END;
	TC←TC+1;
	IF MAPTRC LAND '40000 THEN OUTSTR('11&CVS(TC));
	IF DTRACE THEN OUT(DCHAN,CL&CVS(TC)&'11&S);
	END "DTRC";

_ line deletion with tracing;

INTERNAL SIMPLE PROCEDURE LINDL(INTEGER L,I);
	BEGIN DISW←1; DTRC("LINDEL:"QC(L)); LINDEL(L,I) END;


_ Produces trace typeouts, and pauses if correct bit is set in MAPTRC.
  Also puts out trace on DSK-file "PARSE.TRC" if bit 12 of MAPTRC is set.;

INTERNAL SIMPLE PROCEDURE QTRCE(STRING S);
	BEGIN "QTRC"
	DTRC(S);
	IF MAPTRC LAND '2000 THEN
		BEGIN
		OUTSTR(CL&S);
		IF MAPTRC LAND '4000 THEN
			BEGIN
			WHILE (ICH←INCHRW)≠":"∧ICH≠"←" DO NOTHING;
			IF ICH="←" THEN MAPTRC←MAPCONV(INSTR(":"))
			END
		END;
	END "QTRC";
_ MLCR, REVIVE, UPPDAL;

_ Pushes LC onto the LCREDE-stack for line LN.;

INTERNAL SIMPLE PROCEDURE MLCR(INTEGER LN,LC);
	BEGIN "MLCR"
	DISW←1;
	DTRC("MLCR:  "QC(LN)QC(LC));
	IF LN THEN LCREDE[LN]←LCREDE[LN] LSH 12 LOR LC
	END "MLCR";


_ Pops LCREDE off top of stack, leaving next-to-newest value.;

INTERNAL SIMPLE PROCEDURE REVIVE(INTEGER LN);
	BEGIN "REVIVE"
	DISW←1;
	DTRC("REVIVE:  "QC(LN));
	IF LN THEN LCREDE[LN]←LCREDE[LN] LSH -12
	END "REVIVE";

_ Updates line-display, and waits for a ":" iff SW is on.;

INTERNAL SIMPLE PROCEDURE UPPDAL(INTEGER SW);
	BEGIN "UPPDAL"
	IF ¬DISW THEN RETURN ELSE DISW←0;
	IF SW>0 THEN
		BEGIN
		LNCRE1←LNCRE0;
		DICH[4]←DICH[5]←DICH[6]←1;
		UPPDAT;
		IF MAPTRC LAND '100000 THEN BEGIN PRECAL; CALC END;
		OUTSTR(" D ");
		LNCRE1←LNCS1
		END;
	IF SW THEN
		BEGIN
		WHILE (ICH←INCHRW)≠":"∧ICH≠"←" DO NOTHING;
		IF ICH="←" THEN MAPTRC←MAPCONV(INSTR(":"))
		END
	END "UPPDAL";
_ UNTST, BREAK;

_ tests cv for active and inactive lines.  Returns zero if all lines
  connected to cv are active or inactive.  If some lines of each type
  are connected, it returns the total number of lines;

SIMPLE INTEGER PROCEDURE UNTST(INTEGER CV);
	BEGIN
	INTEGER L, FL, FLG, N, RET;
	FL ← L ← LVERSI[CV];
	IF FL<0∨LVER[FL]=L THEN RETURN(0);
	FLG ← LACT((FL+1) DIV 2);
	RET ← 0;
	N ← 1;
	WHILE (L←LVER[L])≠FL DO
		BEGIN "UNA"
		IF LACT((L+1) DIV 2) XOR FLG THEN RET←-1;
		N ← N+1;
		END "UNA";
	RETURN(IF RET THEN N ELSE 0);
	END;

_ Breaks cv into two cv's, if necessary, and relinks them to seperate
  active and inactive lines.  New cv contains all inactive lines;

SIMPLE PROCEDURE BREAK(INTEGER CV);
	BEGIN
	INTEGER LN, L, NCV, I, LAD, N;
	IF ¬(N←UNTST(CV)) THEN RETURN;
	L ← LVERSI[CV];
	NCV ← 0;
	LAD ← 1;
	DO	BEGIN "BRA"
		LN ← LVER[L];
		IF ¬LACT((L+1) DIV 2) THEN
			BEGIN "BRB"
			MSCVCO(-L,CV,0);
			MSCVCO(L,-NCV,LAD);
			LAD ← LAD+1;
			IF LAD=2 THEN NCV←LVERCO[L];
			END "BRB";
		L ← LN;
		N ← N-1;
		END "BRA" UNTIL ¬N;
	END;
_ CLUPSC;
_ Cleans up the scene after the isolation of a complete or a best partial,
  i.e. removes (to LCREDE=3000+CURMAP) all unused lines coinciding with
  or contained within any line of the object. Lines of other objects
  linked to common cv's are unlinked and given new cv's;

INTERNAL PROCEDURE CLUPSC;
	BEGIN "CLUPSC" INTEGER IA,IB,IC,IV1, LV, M;
	REAL RL,X1,X2,DIFX,DIFY,Y1,Y2;
	SAFEX INTEGER ARRAY MP[1:MAXNOV];
	DEFINE BK(CV)="IF ¬MP[CV] THEN BEGIN BREAK(CV);MP[CV]←1;END",
		RESET="LNCRE1←LNCS1; LNCRE2←LNCS2";
	MP[1] ← 0;
	ARRBLT(MP[2],MP[1],MAXNOV-1);
	N1←2000+2*CURMAP;
	RWIC←2.0*RWIC;
	M ← N1-1;
	LOOP(IA,1,MAXNOL,1) IF M≤LCRL(IA)≤N1 THEN
		BEGIN "CLA"
		LNCRE1←(LNCRE2←N1)-1;
		IB←2*IA;
		X1←XVCOR[IV1←LVERCO[IB-1]];
		Y1←YVCOR[IV1];
		BK(IV1);
		X2←XVCOR[IV1←LVERCO[IB]];
		Y2←YVCOR[IV1];
		BK(IV1);
		REKOP(X1+(DIFX←RWIC*(X1-X2)/(RL←RLEN[IA])),
			Y1+(DIFY←RWIC*(Y1-Y2)/RL),
			X2-DIFX,
			Y2-DIFY,
			RWIC,
			RL);
		RESET;
		LOOP(IB,1,MAXNOL,1) IF LNCRE1≤LCREDE[IB] LAND '400000007777
			    ≤LNCRE2∧ANGLIN(IA,IB)<RMAP
			∧INREK(XVCOR[IV1←LVERCO[(IC←2*IB)-1]],YVCOR[IV1])
			∧INREK(XVCOR[IV1←LVERCO[IC]],YVCOR[IV1])
		   THEN	BEGIN "CLB"
			MLCR(IB,LNCRE1←LNCRE2←3000+CURMAP);
			BK(IV1);
			IV1←LVERCO[IC-1];
			BK(IV1);
			RESET;
			END "CLB";
	        END "CLA";
	LNCRE1←(LNCRE2←N1)-1;
	LOOP(IA,1,MAXNOV,1) IF ¬MP[IA]∧BELCRE(IA) THEN
		WEIGHV(IA,XVCOR[IA],YVCOR[IA],RL);
	RESET;
	RWIC←RWIC/2.0
	END "CLUPSC";
_ FUSABL;

_ Returns -1 (else 0) iff L2>0 and lines of s.v:s V1 and V2 are collinear.
  If L2≤0, we check whether line of s.v. L1 may be extended through V1
	(if L2=0) or V2 (if L2=-1).;

INTERNAL SIMPLE INTEGER PROCEDURE FUSABL(INTEGER L1,L2,V1,V2);
	BEGIN "FUSABL"
	INTEGER IL1;
	IL1←(L1+1)%2;
	DTRC("FUSABL:  "QC(L1)QC(L2)QC(V1)QC(V2));
	IF L2>0∧(ABS LINK[V1]=V2 ∨ ABS LINK[V2]=V1) THEN RETURN(-1);
    	IF L2≤0 THEN
	   RETURN(ABS(CXL[IL1]
			*XVCOR[N1←CASE -L2 OF(V1,V2)]
			+CYL[IL1]
			*YVCOR[N1]
			+CCL[IL1])
		   ≤RWIC
		   *SQRT((XVCOR[N1]-XLCOR[L1])↑2+(YVCOR[N1]-YLCOR[L1])↑2)
		   /RLEN[IL1]);
	RETURN(KARN(XLCOR[V1]
		   ,YLCOR[V1]
		   ,XLCOR[IL1←LVOPP(V1)]
		   ,YLCOR[IL1]
		   ,XLCOR[V2]
		   ,YLCOR[V2]
		   ,XLCOR[IL1←LVOPP(V2)]
		   ,YLCOR[IL1],-1)=1)
	END "FUSABL";
_ LFDIF;

_ Returns encoded actions to be performed at end ND2 of LF2 in order to
  make it similar to end ND1 of LF1. Other ends must agree (otherwise
  error-return = '400). The program also sets the sequential modification
  word (MODIF). MODIF contains two bits for each line-position at ND2 of
  LF2, telling what to do at that position:
  {(0 = no change)(1 = insert line here)(2 = delete line here)
	(3 unused code)}.
  MODIF←-1 if there is no unambiguous modification possible.
  MODIF has its high bit turned on iff end single before insertions.
  The program pays no attention to the outer angle at ND2 of LF2.;

INTERNAL SIMPLE INTEGER PROCEDURE LFDIF(INTEGER LF1,LF2,ND1,ND2);
	BEGIN "LFDIF"
	INTEGER C1,C2,N1,N2,NLDIF,PAR,IA,IB,DEL,CH,IRET,INS,D1,D2,IPD,
		DS1,DS2,CHAR,POS1,POS2,INSTOT,NTOT,BARAM;

_	DN is displacement for other ends. DSN originally points to
	"#lines>180", later to "#lines≤180". CN = constellation bits.
	CH=INS∨DEL all refer to first or last line respectively.;

	LABEL OU;
	DS1←31-(D1←18*ND1);
	DS2←31-(D2←18*ND2);
	MDCTR←IRET←INSTOT←NTOT←BARAM←0;
	MODIF←2;
	RAYS←BITS(LF1,DS1,DS1+3);
	IF ((LF1 LSH (-D1)) XOR (LF2 LSH (-D2))) LAND '367500 THEN
		BEGIN MODIF←-1; IRET←'400; GO OU END;

	_ The other ends are in agreement.;

	LOOP(IA,1,2,1)
		BEGIN
		C1←BITS(LF1,3+D1,4+D1);
		C2←BITS(LF2,3+D2,4+D2);
		INS←(C2=2∧(C1 LAND 1)∨C2∧¬C1);
		CH←-((DEL←C1∧¬C2∨C1=2∧(C2 LAND 1))∨INS);
		PAR←C1 LAND 1;
		IPD←INS∨PAR∧¬DEL;
		IRET←((IRET LSH 1 LOR CH) LSH 1 LOR (-DEL)) LSH 1 LOR PAR;
		NLDIF←(N1←BITS(LF1,DS1,DS1+3))-
			(N2←BITS(LF2,DS2,DS2+3))+INS-DEL;
		IRET←(   (   (   (IRET LSH 1 LOR(-(NLDIF<0)))
				  LSH 4 LOR ABS NLDIF)
			      LSH 4 LOR (POS1←IF IA=2 THEN 1 ELSE
					  IF IPD THEN 2 ELSE 1))
			  LSH 4 LOR (POS2←(IF NLDIF≥0 THEN N1 ELSE N2-INS+DEL)
					+(IA=2∧IPD)))
			  LSH 2 LOR (CHAR←IF ¬CH∧¬NLDIF THEN -(N1>0) ELSE
		  			  IF ¬NLDIF THEN 2 ELSE
					  IF ABS NLDIF=POS2-POS1+1 THEN 2 ELSE
					  	(BARAM←2)+1);
		IF CHAR<2 THEN MODIF←MODIF LSH (2*N1) ELSE
			BEGIN
			IF IA=1∧(CH∨PAR) THEN
				MODIF←MODIF LSH 2 LOR (-INS-2*DEL);
			N2←IF NLDIF<0 THEN N2+(DEL∨PAR∧¬INS) ELSE N1+IPD;
			LOOP(IB,1,N2,1)
			   MODIF←MODIF LSH 2 LOR
				(IF CHAR=3 THEN 3 ELSE
				 IF NLDIF>0 THEN 1 ELSE
				 IF ¬NLDIF THEN 0 ELSE 2);
			IF IA=2∧(CH∨PAR) THEN
				MODIF←MODIF LSH 2 LOR (-INS-2*DEL)
			END;
		D1←18-D1;
		D2←18-D2;
		DS1←DS1-5;
		DS2←DS2-5;
		INSTOT←INSTOT-INS+(0 MAX NLDIF);
		NTOT←NTOT+N1
		END;
	START_CODE LABEL L1, L2;
	SKIPG 1,MODIF;
	JRST L2;
	MOVE 2,MDCTR;
L1:	LSH 1,2;
	ADDI 2,2;
	JUMPG 1,L1;
	MOVEM 2,MDCTR;
	MOVEM 1,MODIF;
L2:	END;

	MODIF←(MODIF LAND '177777777777) LOR ((BARAM-(INSTOT=NTOT)) LSH 34);
OU:	DTRC("LFDIF:  "QCO(LF1)QCO(LF2)QC(ND1)QC(ND2)QCO(IRET)QCO(MODIF));
	RETURN(IRET)
	END "LFDIF";
_ MAP (VCRKEY);

_ Sets up the expanded parallel datastructure for prototype PROT.
  Then initializes mapping arrays according to the basic mapping
  provided by the key feature FEAT (c.f. or l.f.) from the scene
  into the prototype. Then calls MAPREC to complete the mapping,
  described in PLMAP (scene-line corresponding to prot.-line)
  and in PVMAP (scene-vertex corresponding to prot.-vertex).;

INTERNAL INTEGER PROCEDURE MAP(INTEGER LSC,LPR,DIR);
	BEGIN "MAP"
	INTEGER IA,PLNE,SHFT,IB;
	SAFE INTERNAL INTEGER ARRAY LENDV,LENDP,LLEV,LLEVO,PLMAPO[1:PLIN,0:1],
		MAPORD,PARCLA,LENCAT,INSLEV,LFTSTL[1:PLIN],VLEV[1:PVER];
	SAFE EXTERNAL INTEGER ARRAY PLMAP[1:1,0:1],FLMAPS,PVMAP[1:1],
		PARTS[0:1,1:63];

	_ Returns 1 (else 0) iff present key is unexplored (virgin).;

	SIMPLE INTEGER PROCEDURE VIRKEY;
		BEGIN "VIRKEY"
		INTEGER IA,IB;
		IB←((LSC LSH 12 LOR PROT) LSH 12 LOR LPR) LSH 1 LOR DIR;
		IF FTSW THEN LOOP(IA,1,FLMIND,1) 
			IF FLMAPS[IA]=IB THEN RETURN(0) ELSE
				ELSE FLMAPS[FLMIND←FLMIND+1]←IB;
		RETURN(1)
		END "VIRKEY";

	QTRC(CL&"PROT= "&CVS(PROT)&"  LPR= "&CVS(LPR)&"  LSC= "&CVS(LSC)&
	     "  DIR= "&CVOS(DIR)&CL);
	LFDBT←(DIR LSH -1) LAND 1 XOR (DIR←DIR LAND 1);
	IF ¬LACT(LSC)∨¬VIRKEY THEN
		BEGIN
		QTRC(CL&"Key not virgin"&CL);
		RETURN(-1)
		END;
	IF MAPTRC LAND '20000 THEN 
		BEGIN
		OUTSTR("NEW KEY - MAPTRC? ");
		IF INCHRW="←" THEN MAPTRC←MAPCONV(INSTR(":"));
		OUTSTR(CL)
		END;

	_ First set up expanded prototype datastructure,
	  and zero line-mapping arrays.;

	LOOP(IA,1,PLIN,1)
		BEGIN
		PARCLA[IA]←(PLNE←PLINE[AD0+IA]) LAND '37;
		LENCAT[IA]←PLINE2[AD0+IA] LSH -9 LAND 1;
		LOOP(IB,0,1,1)
			BEGIN
			PLMAP[IA,IB]←LLEV[IA,IB]←0;
			LENDV[IA,IB]←BITS(PLNE,30-(SHFT←6*IB),35-SHFT);
			LENDP[IA,IB]←BITS(PLNE,18-SHFT,23-SHFT)
		        END
		END;
	LOOP(IA,1,PVER,1) PVMAP[IA]←VLEV[IA]←0;

	_ Initialize the mapping (1 line) and call on MAPREC to do the job.;

	MAPORD[1]←LPR;
	MLCR(LSC,1001);
	PLMAP[LPR,1-LFDBT]←2*LSC-(DIR XOR LFDBT);
	LLEV[LPR,1-LFDBT]←1;
	PARTS[CMPIND,0]←PROT; KMP←1;
	RETURN(MAPREC)
	END "MAP";
_ PARSE;


_ Will attempt to find a satisfactory parsing of the scene. Note that the
  PARTS-storage implementation limits the number of lines to 511.;

INTERNAL PROCEDURE PARSE;
	BEGIN "PARSE"
	LABEL ITER,REP,REV,ISO,BA1;
	SAFE INTERNAL INTEGER ARRAY PLMAP[1:MAXPLS,0:1],PVMAP[1:MAXPVS],
		PARTS[1:63,0:1+MAXPLS%3],FLMAPS[1:MAXNOV];
	INTEGER MAXCOM,IA,IB,KADR,PFP,CFP,PRP,SCL1,SCL2,PRL1,PRL2,
		LB,UB,FTI,UBI,DIR,IBB,ICC,
		ORD,SUCC,IC,ID,MXMXCM,I1,I2,I3,REVER,PARTSI;


	_ Returns s.v.-entry in PARTS, corresponding
	  to prototype line L of mapping M.;

	INTERNAL SIMPLE INTEGER PROCEDURE LPARTS(INTEGER M,L);
		RETURN(BITS(PARTS[M,IBB←(L+2)%3],ICC←12*(3*IBB-L),ICC+11));

	_ Returns line indicated in LPARTS(M,L), 0 iff no line specified.;

	INTERNAL SIMPLE INTEGER PROCEDURE LPARTL(INTEGER M,L);
		RETURN(((IF (IBB←LPARTS(M,L) LAND '1777)≠'1777 THEN IBB
			ELSE 0)+1)%2);

	LNCRE0←LNCS1←LNCRE1;
	LNCS2←LNCRE2;
	IF MAPTRC=-1 THEN
		BEGIN
		MAPTRC←0;
		LOOP(IA,1,MAXNOL,1)
			BEGIN
			WHILE (IB←LCRL(IA))>2000 DO REVIVE(IA);
			IF IB=1001 THEN REVIVE(IA) ELSE
			    IF IB≥1002∧IB≤1005 THEN LINDL(IA,0)
			END;
		UNXREF;
		UPPDAL(0);
		RETURN
		END;
	DTRACE←MAPTRC LAND '10000;
	DCHAN←NPRS←-1;
	QTRC(CL&"PARSER RESULTS:"&CL);
_ PARSE cont;

	_ Initialize PFPTR.;

	TC←TCS←CURMAP←0;
	PARTSI←1+MAXPLS%3;
REP:	LB←PLFTOT+1;
	UB←PFTOT;
	UBI←1;
	FTSW←FLMIND←0;
	QTRC("CF-keys"&CL);
    	XREFC(0);
	FTEX;

	_ Display scene?;

     	IF MAPTRC LAND '1000000 THEN
		BEGIN
		OUTSTR(CL&"SCENE");
		UPPDAL(MAPTRC LAND '2000000)
	        END;
	LOOP(IA,1,PFTOT,1) PFPTR[IA]←PFPTR[IA] LAND '377777777777;

	_ Find un-exhausted key of maximum complexity.;

	MXMXCM←BESTMP←0;
	CMPIND←(CURMAP←CURMAP+1)+1;
	PARTS[CMPIND,0]←1;
	LOOP(IA,1,MAXNOV,1) FLMAPS[IA]←0;
ITER:	MAXCOM←KMP←SUCC←0;
	LOOP(IA,UB,LB,-1) IF MAXCOM<PFPTR[IA] THEN
		IF(MAXCOM←PFPTR[KADR←IA])=MXMXCM THEN DONE;
	IF ¬MAXCOM THEN GO ISO;
	MXMXCM←MAXCOM;
_ PARSE cont;

	_ Now exhaust the mappings where this feature serves as the key.;

	CFP←BITS(IC←PFPTR[KADR],12,23);
	ORD←IC LAND '4000000000;
	DTRC(" "QC(KADR)QC(CFP)QC(ORD));
	LOOP(FTI,1,UBI,1) IF ¬FTSW∨LNCRE1≤LCREDE[FTI] LAND '400000007777
		≤LNCRE2∧((IB←LFEAT[FTI])<0∧
	   FTSW=2∨IB>0∧FTSW=1)∧KADR=IB LAND '7777 THEN
	   WHILE (CFP←CFP+FTSW) DO
		BEGIN "CFPL"
		SCL1←IF FTSW THEN FTI ELSE BITS(IC←CFEAT[CFP],24,34);
		IF ¬FTSW THEN SCL2←BITS(IC,12,22);
		PRP←PFPTR[KADR] LAND '7777;
		WHILE PRP DO
			BEGIN "PRPL"
			PROT←BITS(PFPRO[PRP],24,35);
			AD0←PPTRL[PROT]-1;
			PLIN←PLINES[PROT];
			PVER←PVERTS[PROT];
			PFP←BITS(PFPRO[PRP],12,23)+1;
			WHILE PFP>1 DO
				BEGIN "PFPL"
				PRL2←PRL1←BITS(IB←PFEAT[PFP],24,33);
				IF ¬FTSW THEN PRL2←BITS(IB,12,21);
				QTRC(CL&"FEAT: "&CVS(KADR)&"  SC-LNS: "&
					CVS(SCL1)&BL&CVS(SCL2)&
					"  PROT: "&CVS(PROT)&"  PR-LNS: "&
					CVS(PRL1)&BL&CVS(PRL2)&CL);
				DIR←IF FTSW THEN
				   LFEAT[FTI] LSH -33 ELSE
				   BITS(IB,34,34) XOR (ID←BITS(IC,35,35));
				SUCC←MAP(SCL1,PRL1,DIR);
				REVER←0;
BA1:				IF SUCC≥0∧MAPTRC LAND '100 THEN
					BEGIN
					OUTSTR(CL&"BEST(MAP) - PROT: "&
						PNAME[PROT]QSCOR&CL);
					LNCRE0←LNCRE2←1006;
					LOOP(I1,1,PLIN,1)
						MLCR(LPARTL(CMPIND,I1),1006);
					UPPDAL(MAPTRC LAND '200);
					LNCRE0←LNCS1;
					LNCRE2←LNCS2;
					LOOP(I1,1,PLIN,1)
						REVIVE(LPARTL(CMPIND,I1))
					END;
				CASE SUCC+1 OF BEGIN GO REV; ; GO ISO; ; END;
_ PARSE cont;
_				 We have here a maximal partial mapping for
				this key.  See if it is a maximal partial
				for this iteration of PARSE. If it is,
				then save inserted lines at LCREDE=1005.;

		 		I3←¬BESTMP
				    ∨SUCC=2
				    ∨PARTS[CMPIND,0] LAND '777777777
					> PARTS[BESTMP,0] LAND '777777777;
				IF I3 THEN
					BEGIN
					BESTMP←CMPIND;
					QTRC(CL&"New best partial"&CL)
				        END;
				LOOP(IA,1,MAXNOL,1)
					IF (I2←LCRL(IA))=1005
					    ∧I3
					    ∨I2=1004
					    ∧¬I3
						THEN LINDL(IA,0) ELSE
					IF I3∧I2=1004 THEN
						LCREDE[IA]←LCREDE[IA]+1;
				IF SUCC=2 THEN GO ISO;
				IF (CMPIND←CMPIND+1)>63 THEN
					BEGIN
					QTRC(CL&"Mappings in excess of 63."&
						"Isolate best."&CL);
					GO ISO
					END;
REV:				IF ¬REVER∧ORD THEN
					BEGIN
					SUCC←MAP(SCL1,PRL2,IF FTSW THEN 1-DIR
						ELSE BITS(IB,22,22) XOR ID);
					REVER←1;
					GO BA1
				        END;

_				Display scene?;

				IF SUCC+1∧KMP∧MAPTRC LAND '200000 THEN
					BEGIN
					OUTSTR(CL&"SCENE");
					UPPDAL(MAPTRC LAND '400000)	
				        END;	
_ PARSE cont;
_				Parsing process continues normally with next
				key ( = scene-line(s) & prototype &
				prototype-line(s) combination).;

				PFP←PFEAT[PFP] LAND '7777
			        END "PFPL";
			PRP←PFPRO[PRP] LAND '7777
			END "PRPL";
		CFP←IF FTSW THEN -FTSW ELSE CFEAT[CFP] LAND '7777;
                END "CFPL";

_	Iterate at this point, starting by finding the best
	unused key-feature at this stage.;

	PFPTR[KADR]←PFPTR[KADR] LOR '400000000000;
	GO ITER;

_	Use l.f. keys as well, before deciding on mapping.;

ISO:	IF SUCC<1∧FTSW<2 THEN
		BEGIN
		FTSW←FTSW+1;
		LB←1;
		UB←PLFTOT;
		UBI←MAXNOL;
		SCL2←PRL2←MXMXCM←0;
		IF FTSW=2 THEN LOOP(IA,1,PLFTOT,1) PFPTR[IA]←
			PFPTR[IA] LAND '377777777777;
		QTRC((CASE FTSW OF("L","L","P"))&"F-keys"&CL);
		GO ITER
                END;

_	Isolation of partial (or complete) object.;
_	First check if the parsing process is at an end.;

	IF ¬BESTMP∧¬SUCC THEN
		BEGIN
		QTRC(CL&"SCENE EXHAUST ED  -  END OF PARSE"&CL);
		DTRACE←MAPTRC←0;
		IF DTRACE THEN BEGIN CLOSE(DCHAN); DCHAN←-1;END;
		RETURN
 	        END;

_	There is a partial or complete. Save mapping.;

	I2← IF SUCC=1 THEN CMPIND ELSE BESTMP;
	LOOP(I1,0,PARTSI,1) PARTS[CURMAP,I1]←PARTS[I2,I1];
_ PARSE cont;

_	Now truck object off to LCREDE=2000+2*CURMAP.;

	CMPIND←2000+2*CURMAP;
	I2←PLINES[N1←PARTS[CURMAP,0] LSH -30];
	LOOP(I1,1,I2,1) MLCR(I3←LPARTL(CURMAP,I1),CMPIND+(LCRL(I3)≠1004));
	IF MAPTRC LAND '400 THEN
		BEGIN
		OUTSTR(CL&"BEST(PARSE) - PROT: "&PNAME[N1]QSCOR&CL);
		LNCRE0←LNCRE2←1006;
		LOOP(I1,1,I2,1) MLCR(LPARTL(CURMAP,I1),1006);
		UPPDAL(MAPTRC LAND '1000);
		LNCRE0←LNCS1;
		LNCRE2←LNCS2;
		LOOP(I1,1,I2,1) REVIVE(LPARTL(CURMAP,I1))
		END;

_	 Finally clean up the scene, shipping all replaced lines
	(partial lines belonging to the object but superceded as members
	of the mapping) into oblivion at LCREDE=3000+CURMAP;

	CLUPSC;
	IF MAPTRC LAND '4000000 THEN
		BEGIN
		LNCRE1←1;
		LNCRE2←4000;
		REGREF(11);
		LNCRE1←LNCS1;
		LNCRE2←LNCS2;
		END;

_	Now the scene may have changed in some relevant way, so before
	  going through a renewed cross-reference investigation and
	  feature-extraction, and continuing the parse, we perform an
	  UNXREF to detach topologically all removed or transferred lines.;

	UNXREF;
	GO REP
	END "PARSE";
END "MAPS1";